/**
 * @file apdu_assembler.c
 * @brief APDU组装器实现
 * @details 本文件实现了104协议的APDU组装器功能，包括I格式、S格式、U格式APDU的
 *          组装、APDU构建辅助函数等核心功能。支持完整的APDU数据组装流程，确保
 *          生成的APDU数据符合104协议规范，包含完整的错误处理和参数验证。
 * 
 * @author zyb
 * @date 2025-10-06
 * @version 1.0
 * 
 * @note I格式APDU包含ASDU数据，S格式和U格式APDU不包含ASDU数据
 * @warning APDU组装时需要确保序列号在有效范围内，避免序列号溢出
 * 
 * @see apdu_assembler.h
 * @see protocol_types.h
 * @see constants.h
 * @see error_codes.h
 */

#include "apdu_assembler.h"
#include "../../common/types/include/protocol_types.h"
#include "../../common/types/include/constants.h"
#include "../../common/error/include/error_codes.h"
#include "../../../../../common/utils/include/buffer_utils.h"
#include "../../../common/logs/include/logger.h"
#include <string.h>

// 定义模块名称
#define LOG_MODULE_NAME "APDU_ASSEMBLER"

/* ==================== I格式APDU组装函数实现 ==================== */

/**
 * @brief 组装I格式APDU
 * @details 将I格式APDU结构体组装成字节流格式。I格式APDU用于传输信息数据，
 *          包含启动字符、长度、控制域（发送/接收序列号）和ASDU数据。
 *          函数会验证APDU格式和缓冲区大小，然后将APDU数据写入缓冲区。
 * 
 * @param apdu I格式APDU结构指针，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为APDU_MIN_LENGTH
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_APDU_FORMAT_ERROR: APDU格式错误
 * 
 * @note I格式APDU包含ASDU数据，长度可变
 * @warning 缓冲区必须足够大以容纳完整的APDU数据
 * 
 * @see apdu_t
 * @see is_i_format_apdu
 * @see validate_apdu
 */
protocol_error_t assemble_i_format_apdu(const apdu_t* apdu, uint8_t* buffer, size_t buffer_size, size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "apdu=%p, buffer=%p, buffer_size=%zu, actual_size=%p", 
                   apdu, buffer, buffer_size, actual_size);
    
    // 参数验证
    LOG_DEBUG(LOG_MODULE_NAME, "APDU指针: %p, 缓冲区指针: %p, 缓冲区大小: %zu", 
                    apdu, buffer, buffer_size);
    
    if (apdu == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: PROTOCOL_ERROR_NULL_POINTER");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (buffer_size < APDU_MIN_LENGTH) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %zu < %d", buffer_size, APDU_MIN_LENGTH);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: PROTOCOL_ERROR_BUFFER_TOO_SMALL");
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "开始组装I格式APDU");
    LOG_DEBUG(LOG_MODULE_NAME, "APDU信息 - 启动字符: 0x%02X, 长度: %d", 
                  apdu->start, apdu->length);
    
    /* 验证APDU */
    LOG_DEBUG(LOG_MODULE_NAME, "开始验证APDU格式");
    protocol_error_t result = validate_apdu(apdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "APDU验证失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "APDU验证通过");
    
    /* 验证I格式 */
    LOG_DEBUG(LOG_MODULE_NAME, "开始验证I格式");
    if (!is_i_format_apdu(apdu)) {
        LOG_ERROR(LOG_MODULE_NAME, "不是有效的I格式APDU");
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: PROTOCOL_ERROR_APDU_FORMAT_ERROR");
        return PROTOCOL_ERROR_APDU_FORMAT_ERROR;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "I格式验证通过");
    
    size_t offset = 0;
    LOG_DEBUG(LOG_MODULE_NAME, "开始写入APDU数据到缓冲区，起始偏移: %zu", offset);
    
    /* 写入启动字符 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入启动字符: 0x%02X 到偏移 %zu", apdu->start, offset);
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, apdu->start));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "写入启动字符失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    
    /* 写入长度 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入长度: %d 到偏移 %zu", apdu->length, offset);
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, apdu->length));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "写入长度失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    
    /* 写入控制域 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入控制域 - control1: 0x%02X 到偏移 %zu", 
                   apdu->control_field.control1, offset);
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, apdu->control_field.control1));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "写入control1失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "写入控制域 - control2: 0x%02X 到偏移 %zu", 
                   apdu->control_field.control2, offset);
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, apdu->control_field.control2));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "写入control2失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "写入控制域 - control3: 0x%02X 到偏移 %zu", 
                   apdu->control_field.control3, offset);
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, apdu->control_field.control3));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "写入control3失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "写入控制域 - control4: 0x%02X 到偏移 %zu", 
                   apdu->control_field.control4, offset);
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, apdu->control_field.control4));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "写入control4失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "控制域写入完成，当前偏移: %zu", offset);
    
    /* 写入ASDU数据 */
    if (apdu->length > APDU_MIN_LENGTH) {
        size_t asdu_size = apdu->length - APDU_MIN_LENGTH;
        LOG_DEBUG(LOG_MODULE_NAME, "需要写入ASDU数据，大小: %zu", asdu_size);
        
        if (offset + asdu_size > buffer_size) {
            LOG_ERROR(LOG_MODULE_NAME, "缓冲区空间不足: %zu + %zu > %zu", 
                      offset, asdu_size, buffer_size);
            LOG_DEBUG(LOG_MODULE_NAME, "返回错误: PROTOCOL_ERROR_BUFFER_TOO_SMALL");
            return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
        }
        
        if (apdu->asdu_data != NULL) {
            LOG_DEBUG(LOG_MODULE_NAME, "写入ASDU数据，大小: %zu，从偏移 %zu", 
                           asdu_size, offset);
            memcpy(buffer + offset, apdu->asdu_data, asdu_size);
            offset += asdu_size;
            LOG_DEBUG(LOG_MODULE_NAME, "ASDU数据写入完成，当前偏移: %zu", offset);
        } else {
            LOG_WARN(LOG_MODULE_NAME, "ASDU数据指针为空，跳过写入");
        }
    } else {
        LOG_DEBUG(LOG_MODULE_NAME, "APDU长度等于最小长度，无需写入ASDU数据");
    }
    
    *actual_size = offset;
    LOG_DEBUG(LOG_MODULE_NAME, "I格式APDU组装完成，总大小: %zu", offset);
    LOG_DEBUG(LOG_MODULE_NAME, "成功，实际大小: %zu", offset);
    LOG_INFO(LOG_MODULE_NAME, "I格式APDU组装成功，实际大小: %zu", offset);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 组装带ASDU的I格式APDU
 * @details 直接使用ASDU数据组装I格式APDU。这是一个便捷函数，
 *          用于将ASDU数据直接封装成I格式APDU，无需先构建APDU结构。
 *          函数会验证ASDU有效性，设置序列号，然后组装成字节流。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param send_seq 发送序列号
 * @param receive_seq 接收序列号
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效ASDU类型
 * 
 * @note 此函数是assemble_i_format_apdu()的便捷版本
 * @warning 序列号必须在有效范围内（0-32767）
 * 
 * @see asdu_t
 * @see assemble_i_format_apdu
 * @see validate_asdu
 */
protocol_error_t assemble_i_format_apdu_with_asdu(const asdu_t* asdu, 
                                                  uint16_t send_seq, 
                                                  uint16_t receive_seq,
                                                  uint8_t* buffer, 
                                                  size_t buffer_size, 
                                                  size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装带ASDU的I格式APDU: asdu=%p, send_seq=%u, receive_seq=%u", 
              asdu, send_seq, receive_seq);
    
    if (asdu == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证ASDU */
    protocol_error_t result = validate_asdu(asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU验证失败: %d", result);
        return result;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU验证通过");
    
    /* 计算所需缓冲区大小 */
    size_t required_size = APDU_MIN_LENGTH + asdu->length;
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %zu < %zu", buffer_size, required_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小检查通过: %zu >= %zu", buffer_size, required_size);
    
    /* 构建APDU */
    apdu_t apdu;
    result = init_apdu(&apdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "APDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置长度 */
    apdu.length = required_size;
    
    /* 设置控制域（I格式） */
    apdu.control_field.control1 = (send_seq << 1) & 0xFE; /* bit 0 = 0 */
    apdu.control_field.control2 = (send_seq >> 7) & 0xFF;
    apdu.control_field.control3 = (receive_seq << 1) & 0xFE; /* bit 0 = 0 */
    apdu.control_field.control4 = (receive_seq >> 7) & 0xFF;
    
    /* 设置ASDU数据 */
    apdu.asdu_data = (uint8_t*)asdu;
    
    /* 组装APDU */
    result = assemble_i_format_apdu(&apdu, buffer, buffer_size, actual_size);
    if (result == PROTOCOL_SUCCESS) {
        LOG_INFO(LOG_MODULE_NAME, "带ASDU的I格式APDU组装成功，实际大小: %zu", *actual_size);
    }
    return result;
}

/* ==================== S格式APDU组装函数实现 ==================== */

/**
 * @brief 组装S格式APDU
 * @details 组装S格式APDU，用于确认接收到的I格式APDU。S格式APDU
 *          只包含接收序列号，不包含ASDU数据，长度固定为4字节。
 *          用于实现104协议的确认机制。
 * 
 * @param receive_seq 接收序列号，表示已确认接收的I格式APDU序列号
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为4字节
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note S格式APDU长度固定为4字节，不包含ASDU数据
 * @warning 接收序列号必须在有效范围内（0-32767）
 * 
 * @see U_FORMAT_STARTDT_ACT
 * @see U_FORMAT_STARTDT_CON
 * @see U_FORMAT_STOPDT_ACT
 * @see U_FORMAT_STOPDT_CON
 * @see U_FORMAT_TESTFR_ACT
 * @see U_FORMAT_TESTFR_CON
 */
protocol_error_t assemble_s_format_apdu(uint16_t receive_seq, uint8_t* buffer, size_t buffer_size, size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "receive_seq=%u, buffer=%p, buffer_size=%zu, actual_size=%p", 
                   receive_seq, buffer, buffer_size, actual_size);
    
    LOG_DEBUG(LOG_MODULE_NAME, "接收序列号: %u, 缓冲区指针: %p, 缓冲区大小: %zu", 
                    receive_seq, buffer, buffer_size);
    
    if (buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: PROTOCOL_ERROR_NULL_POINTER");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (buffer_size < 4) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %zu < 4", buffer_size);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: PROTOCOL_ERROR_BUFFER_TOO_SMALL");
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "开始组装S格式APDU，接收序列号: %u", receive_seq);
    
    size_t offset = 0;
    
    /* 写入启动字符 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入启动字符: 0x%02X 到偏移 %zu", APDU_START_CHAR, offset);
    protocol_error_t result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, APDU_START_CHAR));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "写入启动字符失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    
    /* 写入长度（S格式固定为4） */
    LOG_DEBUG(LOG_MODULE_NAME, "写入长度: 4 到偏移 %zu", offset);
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, 4));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "写入长度失败: %d", result);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: %d", result);
        return result;
    }
    
    /* 写入控制域（S格式） */
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, 0x01)); /* bit 0 = 0, bit 1 = 1 */
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, (receive_seq << 1) & 0xFE));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, 0x00));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, 0x00));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    *actual_size = offset;
    LOG_INFO(LOG_MODULE_NAME, "S格式APDU组装成功，实际大小: %zu", offset);
    return PROTOCOL_SUCCESS;
}

/* ==================== U格式APDU组装函数实现 ==================== */

/**
 * @brief 组装U格式APDU
 * @details 组装U格式APDU，用于控制功能。U格式APDU不包含序列号，
 *          长度固定为4字节，用于启动/停止数据传输、测试帧等控制功能。
 *          支持STARTDT、STOPDT、TESTFR等控制类型。
 * 
 * @param u_type U格式类型，如STARTDT_ACT、STOPDT_CON等
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为4字节
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效U格式类型
 * 
 * @note U格式APDU长度固定为4字节，不包含序列号和ASDU数据
 * @warning U格式类型必须是有效的控制类型
 * 
 * @see u_format_type_t
 * @see U_FORMAT_STARTDT_ACT
 * @see U_FORMAT_STARTDT_CON
 * @see U_FORMAT_STOPDT_ACT
 * @see U_FORMAT_STOPDT_CON
 * @see U_FORMAT_TESTFR_ACT
 * @see U_FORMAT_TESTFR_CON
 */
protocol_error_t assemble_u_format_apdu(u_format_type_t u_type, uint8_t* buffer, size_t buffer_size, size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装U格式APDU: u_type=%d, buffer=%p, buffer_size=%zu", 
              u_type, buffer, buffer_size);
    
    if (buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (buffer_size < 4) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %zu < 4", buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    size_t offset = 0;
    
    /* 写入启动字符 */
    protocol_error_t result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, APDU_START_CHAR));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    /* 写入长度（U格式固定为4） */
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, 4));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    /* 写入控制域（U格式） */
    uint8_t control1 = 0x03; /* bit 0 = 1, bit 1 = 1 */
    
    switch (u_type) {
        case U_FORMAT_STARTDT_ACT:
            control1 |= 0x04; /* bit 2 = 1 */
            break;
        case U_FORMAT_STARTDT_CON:
            control1 |= 0x08; /* bit 3 = 1 */
            break;
        case U_FORMAT_STOPDT_ACT:
            control1 |= 0x10; /* bit 4 = 1 */
            break;
        case U_FORMAT_STOPDT_CON:
            control1 |= 0x20; /* bit 5 = 1 */
            break;
        case U_FORMAT_TESTFR_ACT:
            control1 |= 0x40; /* bit 6 = 1 */
            break;
        case U_FORMAT_TESTFR_CON:
            control1 |= 0x80; /* bit 7 = 1 */
            break;
        default:
            LOG_ERROR(LOG_MODULE_NAME, "无效的U格式类型: %d", u_type);
            return PROTOCOL_ERROR_INVALID_PARAM;
    }
    
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, control1));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, 0x00));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, 0x00));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, 0x00));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    *actual_size = offset;
    LOG_INFO(LOG_MODULE_NAME, "U格式APDU组装成功，实际大小: %zu", offset);
    return PROTOCOL_SUCCESS;
}

/* ==================== 通用APDU组装函数实现 ==================== */

/**
 * @brief 通用APDU组装函数
 * @details 根据APDU格式自动选择相应的组装函数。这是一个通用接口，
 *          会根据APDU的格式（I格式、S格式、U格式）调用相应的专用组装函数。
 *          支持所有类型的APDU组装。
 * 
 * @param apdu APDU结构指针，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_APDU_FORMAT_ERROR: APDU格式错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 此函数会根据APDU格式自动选择相应的组装函数
 * @warning 确保APDU格式正确，否则会返回格式错误
 * 
 * @see assemble_i_format_apdu
 * @see assemble_s_format_apdu
 * @see assemble_u_format_apdu
 * @see is_i_format_apdu
 * @see is_s_format_apdu
 * @see is_u_format_apdu
 */
protocol_error_t assemble_apdu(const apdu_t* apdu, uint8_t* buffer, size_t buffer_size, size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "通用APDU组装: apdu=%p, buffer=%p, buffer_size=%zu", 
              apdu, buffer, buffer_size);
    
    if (apdu == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 根据APDU格式选择相应的组装函数 */
    if (is_i_format_apdu(apdu)) {
        LOG_DEBUG(LOG_MODULE_NAME, "检测到I格式APDU，调用I格式组装函数");
        return assemble_i_format_apdu(apdu, buffer, buffer_size, actual_size);
    } else if (is_s_format_apdu(apdu)) {
        LOG_DEBUG(LOG_MODULE_NAME, "检测到S格式APDU，调用S格式组装函数");
        return assemble_s_format_apdu(0, buffer, buffer_size, actual_size); /* S格式不需要序列号参数 */
    } else if (is_u_format_apdu(apdu)) {
        LOG_DEBUG(LOG_MODULE_NAME, "检测到U格式APDU，解析U格式类型");
        /* U格式需要从控制域解析类型 */
        u_format_type_t u_type = U_FORMAT_STARTDT_ACT; /* 默认值 */
        if (apdu->control_field.control1 & 0x04) {
            u_type = U_FORMAT_STARTDT_ACT;
        } else if (apdu->control_field.control1 & 0x08) {
            u_type = U_FORMAT_STARTDT_CON;
        } else if (apdu->control_field.control1 & 0x10) {
            u_type = U_FORMAT_STOPDT_ACT;
        } else if (apdu->control_field.control1 & 0x20) {
            u_type = U_FORMAT_STOPDT_CON;
        } else if (apdu->control_field.control1 & 0x40) {
            u_type = U_FORMAT_TESTFR_ACT;
        } else if (apdu->control_field.control1 & 0x80) {
            u_type = U_FORMAT_TESTFR_CON;
        }
        LOG_DEBUG(LOG_MODULE_NAME, "U格式类型: %d，调用U格式组装函数", u_type);
        return assemble_u_format_apdu(u_type, buffer, buffer_size, actual_size);
    }
    
    LOG_ERROR(LOG_MODULE_NAME, "未知的APDU格式");
    return PROTOCOL_ERROR_APDU_FORMAT_ERROR;
}

/* ==================== APDU构建辅助函数实现 ==================== */

/**
 * @brief 构建I格式APDU
 * @details 构建I格式APDU结构，包含发送序列号、接收序列号和ASDU数据。
 *          这是一个便捷函数，用于创建完整的I格式APDU结构。
 * 
 * @param send_seq 发送序列号，范围0-32767
 * @param receive_seq 接收序列号，范围0-32767
 * @param asdu ASDU结构指针，不能为NULL
 * @param apdu APDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 构建成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 *         - PROTOCOL_ERROR_ASDU_INVALID: ASDU无效
 * 
 * @note 构建后的APDU需要调用assemble_apdu()组装成字节流
 * @warning 序列号必须在有效范围内
 * 
 * @see assemble_apdu
 * @see validate_asdu
 * @see init_apdu
 */
protocol_error_t build_i_format_apdu(uint16_t send_seq, uint16_t receive_seq, const asdu_t* asdu, apdu_t* apdu) {
    LOG_DEBUG(LOG_MODULE_NAME, "构建I格式APDU: send_seq=%u, receive_seq=%u, asdu=%p, apdu=%p", 
              send_seq, receive_seq, asdu, apdu);
    
    if (asdu == NULL || apdu == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证ASDU */
    protocol_error_t result = validate_asdu(asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU验证失败: %d", result);
        return result;
    }
    
    /* 初始化APDU */
    result = init_apdu(apdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "APDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置长度 */
    apdu->length = APDU_MIN_LENGTH + asdu->length;
    LOG_DEBUG(LOG_MODULE_NAME, "APDU长度设置: %u (最小长度: %u + ASDU长度: %u)", 
              apdu->length, APDU_MIN_LENGTH, asdu->length);
    
    /* 设置控制域（I格式） */
    apdu->control_field.control1 = (send_seq << 1) & 0xFE; /* bit 0 = 0 */
    apdu->control_field.control2 = (send_seq >> 7) & 0xFF;
    apdu->control_field.control3 = (receive_seq << 1) & 0xFE; /* bit 0 = 0 */
    apdu->control_field.control4 = (receive_seq >> 7) & 0xFF;
    
    /* 设置ASDU数据指针 */
    apdu->asdu_data = (uint8_t*)asdu;
    
    LOG_INFO(LOG_MODULE_NAME, "I格式APDU构建成功: 发送序列号=%u, 接收序列号=%u, 长度=%u", 
             send_seq, receive_seq, apdu->length);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 构建S格式APDU
 * @details 构建S格式APDU结构，用于确认帧传输。
 *          包含接收序列号，用于确认已接收的I格式APDU。
 *          这是一个便捷函数，用于创建完整的S格式APDU结构。
 * 
 * @param receive_seq 接收序列号，范围0-32767
 * @param apdu APDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 构建成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 * 
 * @note 构建后的APDU需要调用assemble_apdu()组装成字节流
 * @warning 序列号必须在有效范围内（0-32767）
 * 
 * @see assemble_apdu
 * @see init_apdu
 * @see S_FORMAT_CONTROL_MASK
 */
protocol_error_t build_s_format_apdu(uint16_t receive_seq, apdu_t* apdu) {
    LOG_DEBUG(LOG_MODULE_NAME, "构建S格式APDU: receive_seq=%u, apdu=%p", receive_seq, apdu);
    
    if (apdu == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 初始化APDU */
    protocol_error_t result = init_apdu(apdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "APDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置长度（S格式固定为4） */
    apdu->length = 4;
    LOG_DEBUG(LOG_MODULE_NAME, "S格式APDU长度设置为4字节");
    
    /* 设置控制域（S格式） */
    apdu->control_field.control1 = 0x01; /* bit 0 = 0, bit 1 = 1 */
    apdu->control_field.control2 = (receive_seq << 1) & 0xFE;
    apdu->control_field.control3 = 0x00;
    apdu->control_field.control4 = 0x00;
    
    LOG_INFO(LOG_MODULE_NAME, "S格式APDU构建成功: 接收序列号=%u", receive_seq);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 构建U格式APDU
 * @details 构建U格式APDU结构，用于控制帧传输。
 *          支持启动数据传输、停止数据传输、测试帧等控制类型。
 *          这是一个便捷函数，用于创建完整的U格式APDU结构。
 * 
 * @param u_type U格式类型，不能为NULL
 * @param apdu APDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 构建成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 * 
 * @note 构建后的APDU需要调用assemble_apdu()组装成字节流
 * @warning U格式类型必须是有效的控制类型
 * 
 * @see assemble_apdu
 * @see init_apdu
 * @see u_format_type_t
 */
protocol_error_t build_u_format_apdu(u_format_type_t u_type, apdu_t* apdu) {
    LOG_DEBUG(LOG_MODULE_NAME, "构建U格式APDU: u_type=%d, apdu=%p", u_type, apdu);
    
    if (apdu == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 初始化APDU */
    protocol_error_t result = init_apdu(apdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "APDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置长度（U格式固定为4） */
    apdu->length = 4;
    LOG_DEBUG(LOG_MODULE_NAME, "U格式APDU长度设置为4字节");
    
    /* 设置控制域（U格式） */
    apdu->control_field.control1 = 0x03; /* bit 0 = 1, bit 1 = 1 */
    
    switch (u_type) {
        case U_FORMAT_STARTDT_ACT:
            apdu->control_field.control1 |= 0x04; /* bit 2 = 1 */
            LOG_DEBUG(LOG_MODULE_NAME, "设置STARTDT_ACT控制位");
            break;
        case U_FORMAT_STARTDT_CON:
            apdu->control_field.control1 |= 0x08; /* bit 3 = 1 */
            LOG_DEBUG(LOG_MODULE_NAME, "设置STARTDT_CON控制位");
            break;
        case U_FORMAT_STOPDT_ACT:
            apdu->control_field.control1 |= 0x10; /* bit 4 = 1 */
            LOG_DEBUG(LOG_MODULE_NAME, "设置STOPDT_ACT控制位");
            break;
        case U_FORMAT_STOPDT_CON:
            apdu->control_field.control1 |= 0x20; /* bit 5 = 1 */
            LOG_DEBUG(LOG_MODULE_NAME, "设置STOPDT_CON控制位");
            break;
        case U_FORMAT_TESTFR_ACT:
            apdu->control_field.control1 |= 0x40; /* bit 6 = 1 */
            LOG_DEBUG(LOG_MODULE_NAME, "设置TESTFR_ACT控制位");
            break;
        case U_FORMAT_TESTFR_CON:
            apdu->control_field.control1 |= 0x80; /* bit 7 = 1 */
            LOG_DEBUG(LOG_MODULE_NAME, "设置TESTFR_CON控制位");
            break;
        default:
            LOG_ERROR(LOG_MODULE_NAME, "无效的U格式类型: %d", u_type);
            return PROTOCOL_ERROR_INVALID_PARAM;
    }
    
    apdu->control_field.control2 = 0x00;
    apdu->control_field.control3 = 0x00;
    apdu->control_field.control4 = 0x00;
    
    LOG_INFO(LOG_MODULE_NAME, "U格式APDU构建成功: 类型=%d, 控制域1=0x%02X", u_type, apdu->control_field.control1);
    return PROTOCOL_SUCCESS;
}
